package org.dam.controller;

import lombok.extern.slf4j.Slf4j;
import org.dam.common.exception.ClientException;
import org.dam.common.result.Result;
import org.dam.common.result.Results;
import org.dam.entity.Task;
import org.dam.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.rmi.ServerException;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author dam
 * @create 2024/1/18 20:37
 */
@RestController
@RequestMapping("/backup")
@Slf4j
public class BackupController {

    @Autowired
    private BackupService backupService;
    @Autowired
    private ClearService clearService;
    @Autowired
    private ThreadPoolExecutor executor;

    /**
     * 存储正在备份的数据源ID
     */
    public HashSet<Long> backupingSourceIDSet = new HashSet<>();

    /**
     * 存储正在备份的数据源ID
     */
    public HashSet<Long> clearingSourceIDSet = new HashSet<>();

    /**
     * 对指定的数据源进行备份
     */
    @GetMapping("/backupBySourceId/{sourceId}")
    public Result backupBySourceId(@PathVariable Long sourceId) throws IOException {
        if (backupingSourceIDSet.contains(sourceId)) {
            throw new ClientException("当前备份源正在备份中，请稍后再试");
        }

        // 检查 备份源目录是否存在 和 准备好备份目标目录
        List<Task> taskList = backupService.checkSourceAndTarget(sourceId);
        if (taskList == null || taskList.size() == 0) {
            removeSourceIdFromBacking(backupingSourceIDSet, sourceId);
            return Results.failure();
        }

        // 开始备份
        backupingSourceIDSet.add(sourceId);
//        backupService.backupBySourceId(sourceId, taskList);
        CompletableFuture.runAsync(() -> {
            try {
                backupService.backupBySourceId(sourceId, taskList);
            } catch (ServerException e) {
                try {
                    throw new ServerException(e.getMessage());
                } catch (ServerException ex) {
                    throw new RuntimeException(ex);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }, executor).exceptionally(throwable -> {
            log.error(throwable.getMessage());
            removeSourceIdFromBacking(backupingSourceIDSet, sourceId);
            return null;
        });

        return Results.success();
    }

    /**
     * 将数据源Id从正在备份的数据源set中移除
     *
     * @param backupingSourceIDSet
     * @param sourceId
     */
    private void removeSourceIdFromBacking(HashSet<Long> backupingSourceIDSet, Long sourceId) {
        if (backupingSourceIDSet.contains(sourceId)) {
            backupingSourceIDSet.remove(sourceId);
        }
    }

    /**
     * 对指定的数据源删除无效数据
     */
    @GetMapping("/clearBySourceId/{sourceId}")
    public Result clearBySourceId(@PathVariable Long sourceId) {

        if (clearingSourceIDSet.contains(sourceId)) {
            throw new ClientException("当前备份源正在清理中，请稍后再试");
        } else {
            clearingSourceIDSet.add(sourceId);
        }

        CompletableFuture.runAsync(() -> {
            clearService.clearBySourceId(sourceId);
            removeSourceIdFromBacking(clearingSourceIDSet, sourceId);
        }, executor).exceptionally(throwable -> {
            log.error(throwable.getMessage());
            removeSourceIdFromBacking(clearingSourceIDSet, sourceId);
            return null;
        });
        return Results.success();
    }

}
